﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using SymbolIntegration.core;
using SymbolIntegration.core.Expressions;
using SymbolIntegration.core.Expressions.Functions;
using SymbolIntegration.core.Helpers;

namespace AnalyticIntegration.DefaultIntergators
{
    public class ExpOrSinOrCosFunctionIntegrator : IIntegrator
    {
        public bool CanIntegrate(List<Expression> multipliers, ExpressionStatistic statistic, string variable)
        {
            bool isCan = false;
            do
            {
                if (statistic.Functions.Count != 1 || statistic.HasUnpolinomicPowers || statistic.HasUnintegratedExpression)
                {
                    break;
                }

                var functionStatistic = statistic.Functions.First();
                if (functionStatistic.Type != FunctionType.Exp && functionStatistic.Type != FunctionType.Cos
                    && functionStatistic.Type != FunctionType.Sin)
                {
                    break;
                }

                if (functionStatistic.ArgumentPolinomMaxPower == null || functionStatistic.ArgumentPolinomMaxPower.Value > 1)
                {
                    break;
                }

                if (multipliers.Count != 2)
                {
                    break;
                }

                isCan = true;
            }
            while (false);

            return isCan;
        }

        public Expression TryIntegrateMultipliers(List<Expression> multipliers, string variable)
        {
            var function = multipliers[0] as FuncExpression;
            Expression otherExpression = null;
            if (function == null)
            {
                function = multipliers[1] as FuncExpression;
                otherExpression = multipliers[0];
            }
            else
            {
                otherExpression = multipliers[1];
            }
            var integratedExp = Expression.Integrate(function, variable, this);
            var firstPartOfResult = integratedExp*otherExpression;
            var secondPartOfResult = otherExpression.Differentiate(variable) * integratedExp;
            secondPartOfResult = Expression.Integrate(secondPartOfResult, variable, this);
            var result = firstPartOfResult - secondPartOfResult;
            return result;
        }
    }
}
